import logging.config
import os
import logging
import sys
from flask import Flask, request, redirect, url_for, render_template, flash
from flask_sqlalchemy import SQLAlchemy
from flask_login import (
    LoginManager,
    UserMixin,
    login_user,
    login_required,
    logout_user,
    current_user,
)
from .containers import *
from .configs import (
    get_config,
    load_config,
    DB_URI,
    TEMPLATE_FOLDER,
    LOCAL_INSTANCE_DATA_PATH,
)
from flask_babel import Babel, gettext as _
from .services.svc_nginx_proxy import NginxManager
from .utils.tasks_manager import TaskManager

logging.basicConfig(stream=sys.stderr, level=logging.INFO)
# import backend
# Create the Flask app

app = Flask(
    __name__,
    template_folder=TEMPLATE_FOLDER,
    static_folder=os.path.join(os.path.dirname(os.path.abspath(__file__)), "static"),
    static_url_path="/static",
)

translation_folder = os.path.join(
    os.path.dirname(os.path.abspath(__file__)), "static", "locales"
)

logger = logging.getLogger(__name__)
logger.info(f"DB URI is: {DB_URI}")


# 在Docker中运行时，必须定义LOCAL_INSTANCE_DATA_PATH这个变量，将持久化数据的
# 路径传入容器，且保证容器中的路径和主机路径一致，从而方便nginx访问
logger.info(f"LOCAL_INSTANCE_DATA_PATH is: {LOCAL_INSTANCE_DATA_PATH}")

_public_programs_path = os.path.join(LOCAL_INSTANCE_DATA_PATH, "public/programs")
_config_path = os.path.join(LOCAL_INSTANCE_DATA_PATH, "configs.json")

load_config(_config_path)
app.config["SQLALCHEMY_DATABASE_URI"] = (
    DB_URI
    if DB_URI != ""
    else f"sqlite:///{os.path.join(LOCAL_INSTANCE_DATA_PATH, 'baco3.db')}"
)

app.config["SECRET_KEY"] = get_config()["secret_key"]
app.config["SESSION_COOKIE_NAME"] = (
    "baco3_session"  # 修改默认 session cookie 名称为 baco3_session
)

nginx_manager = NginxManager(
    nginx_data_dir=os.path.join(LOCAL_INSTANCE_DATA_PATH, "nginx")
)
tasks_manager = TaskManager(pool_size=10)
babel = Babel()


def get_locale():
    # print( "locale!",request.accept_languages.best_match(["zh_CN", "en"]))
    return request.accept_languages.best_match(["zh", "en"])


def get_public_programs_path():
    """
    Get the programs path that storing common code editors.
    """
    if not os.path.exists(_public_programs_path):
        os.makedirs(_public_programs_path)
    return _public_programs_path


def init_app():
    # with pkg_resources.as_file(traversable) as path:
    assert os.path.exists(translation_folder)
    babel.init_app(
        app,
        default_translation_directories=translation_folder,
        locale_selector=get_locale,
        default_locale="zh_CN",
    )


init_app()


# env = Environment()
def zip_lists(list1, list2):
    return zip(list1, list2)


def zip_lists_3(list1, list2, list3):
    return zip(list1, list2, list3)


app.jinja_env.filters["zip"] = zip_lists
app.jinja_env.filters["zip3"] = zip_lists_3
app.jinja_env.filters["zip4"] = lambda list1, list2, list3, list4: zip(
    list1, list2, list3, list4
)
app.jinja_env.filters["boolean"] = lambda x: "true" if x else "false"
app.jinja_env.filters["split"] = lambda x, splitter: x.split(splitter)
app.jinja_env.filters["stripSpaces"] = lambda x: x.strip()
app.jinja_env.filters["strip"] = lambda x, y: x.strip(y)

db = SQLAlchemy(app)


class OperationalError(BaseException):
    # 用户操作导致的错误，错误码一般为400
    def __init__(self, msg):
        self.msg = msg


@app.errorhandler(401)
def unauthorized_access(error):
    return redirect(url_for("login"))  # 假设登录页面的路由名为 'login'


@app.route("/not_found_page")
def error_not_found_page():
    return render_template("404.html"), 404


@app.context_processor
def inject_variables():
    routes = [
        {"text": _("Dev Envs"), "href": "container_mgr/dashboard"},
        {"text": _("Dev Images"), "href": "dev_env_imgs/editpanel"},
        {"text": _("Host Machines"), "href": "host-machine-info/view"},
        {"text": _("User Info"), "href": "user_info"},
        {"text": _("Background Tasks"), "href": "background_tasks/view"},
    ] + (
        [{"text": _("Snapshots"), "href": "snapshots/view"}]
        if get_config()["dev_mode"]
        else []
    )
    username = "<Not Login>"
    # If the user is "admin", add a logout route
    if hasattr(current_user, "username"):
        if current_user.username == "admin":
            routes.append({"text": _("User Management"), "href": "users_manage"})
        username = current_user.username
    return {"routes": routes, "username": username}
